import storage from "./storage.js";
import pagesJson from "@/pages.json";
const tabBarConfig = pagesJson.tabBar;
const tabBarList = tabBarConfig ? tabBarConfig.list : [];
const pagesList = pagesJson.pages;
const subList = pagesJson.subPackages;

// 注册钩子函数对象，用于存储 beforeEach 和 afterLogin 等钩子函数
const fn = {};
class Router {
  constructor() {}
  // -------------------- 静态方法 --------------------
  /**
   * 拼接参数
   * @param {*} query 参数对象
   * @returns {string} 拼接后的参数
   */
  static objectToUrlQuery(query) {
    if (!query) return "";
    const queryVal = [];
    for (const key in query) {
      if (Object.prototype.hasOwnProperty.call(query, key)) {
        const value = query[key];
        // 过滤掉空字符串、undefined、null
        if (value !== "" && value !== undefined && value !== null) {
          queryVal.push(`${key}=${value}`);
        }
      }
    }
    return queryVal.join("&");
  }
  /**
   * 移除字符串的第一个字符（仅当第一个字符为 / 时）
   * @param {string} str - 需要处理的字符串
   * @returns {string} 处理后的字符串
   */
  static removeLeadingSlash(str) {
    if (typeof str !== "string") {
      throw new Error("输入必须是字符串类型");
    }
    if (str.length > 0 && str[0] === "/") {
      return str.slice(1);
    } else {
      return str;
    }
  }
  // -------------------- 其他方法 --------------------
  /**
   * 判断指定路径是否为Tab页面
   * @param {string} path - 要判断的路径
   * @returns {boolean} 是否为Tab页面
   */
  isTab(path) {
    // 在tabs配置中查找是否有匹配的路径
    return tabBarList.some((e) =>
      e.pagePath.includes(Router.removeLeadingSlash(path))
    );
  }
  /**
   * 判断当前是否为第一个页面
   * 用于决定返回操作是返回上一页还是跳转首页
   * @returns {boolean} 是否为第一个页面
   */
  isFirstPage() {
    return getCurrentPages().length == 1; // 页面栈长度为1表示当前是第一个页面
  }

  /**
   * 获取所有页面配置
   * @returns {Object} 包含tabbar、pages和sub的页面配置对象
   */
  get pages() {
    return {
      tabbar: tabBarList,
      pages: pagesList,
      sub: subList,
    };
  }

  // -------------------- router 主要方法 --------------------
  /**
   * 页面跳转主函数
   * 支持多种跳转模式，自动处理参数拼接，支持导航守卫
   * @param {Object|string} options - 跳转选项或目标路径字符串
   * @param {string} options.path - 目标页面路径
   * @param {Object} [options.query] - URL查询参数
   * @param {string} [options.mode='navigateTo'] - 跳转模式，支持navigateTo/redirectTo/reLaunch/switchTab/preloadPage
   * @param {string} [options.animationType] - 动画类型
   * @param {number} [options.animationDuration] - 动画持续时间
   * @param {Object} [options.params] - 非URL参数，通过storage传递
   * @param {Object} [options.events] - 页面间通信事件
   * @param {Function} [options.success] - 成功回调
   * @param {Function} [options.fail] - 失败回调
   * @param {Function} [options.complete] - 完成回调
   * @param {boolean} [options.guard=true] - 是否启用导航守卫
   */
  push(path, options = {}) {
    let {
      query,
      params,
      mode = "navigateTo", // 默认使用 navigateTo 模式
      animationType,
      animationDuration,
      events,
      success,
      fail,
      complete,
      guard = false, // 默认不启用导航守卫
    } = options;
    let url = `/${Router.removeLeadingSlash(path)}`;
    if (query) {
      url += `?${Router.objectToUrlQuery(query)}`;
    }

    // 将复杂参数存入storage缓存
    if (params) {
      storage.set("router-params", params);
    }

    // 准备传递给uni路由API的参数
    const data = {
      url,
      animationType,
      animationDuration,
      events,
      success,
      fail,
      complete,
    };
    // 如果目标是tab页，强制使用switchTab模式
    if (this.isTab(path)) {
      mode = "switchTab";
    }
    // 实际执行跳转的函数
    const next = () => {
      switch (mode) {
        case "navigateTo": // 保留当前页面，跳转到应用内的某个页面
          uni.navigateTo(data);
          break;
        case "redirectTo": // 关闭当前页面，跳转到应用内的某个页面
          uni.redirectTo(data);
          break;
        case "reLaunch": // 关闭所有页面，打开到应用内的某个页面
          uni.reLaunch(data);
          break;
        case "switchTab": // 跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面
          uni.switchTab(data);
          break;
        case "preloadPage": // 预加载页面，但不跳转
          uni.preloadPage(data);
          break;
      }
    };

    // 执行导航守卫
    if (fn.beforeEach && guard) {
      // 调用beforeEach钩子，传入目标路径、参数、next函数和重定向函数
      fn.beforeEach({ path, query }, next, (opt) => this.push(opt));
    } else {
      // 没有设置导航守卫或禁用了守卫，直接执行跳转
      next();
    }
  }
  /**
   * 路由返回
   * @param {*} delta 返回层数
   */
  back(delta = 1) {
    const pages = getCurrentPages();
    if (pages.length > delta) {
      uni.navigateBack({
        delta,
      });
    } else {
      uni.switchTab({
        url: `/${
          tabBarList[0].pagePath ? tabBarList[0].pagePath : pagesList[0].path
        }`,
      });
    }
  }

  /**
   * 跳转到指定的Tab页面
   * @param {string} name - Tab页面的名称或路径的一部分
   */
  switchTab(name) {
    // 在tabBarList配置中查找包含指定名称的页面
    const item = this.pages.tabbar.find((e) =>
      e.pagePath.includes(Router.removeLeadingSlash(name))
    );
    if (item) {
      // 找到对应的tab页，使用switchTab模式跳转
      this.push({
        path: `/${item.pagePath}`,
        mode: "switchTab",
      });
    } else {
      // 未找到对应的tab页，输出错误信息
      console.error("未找到选项卡：", name);
    }
  }
  /**
   * 注册路由前置守卫
   * @param {Function} callback - 守卫回调函数
   * @param {Object} callback.to - 目标路由信息
   * @param {Function} callback.next - 继续导航的函数
   * @param {Function} callback.redirect - 重定向函数
   */
  beforeEach(callback) {
    fn.beforeEach = callback;
  }
}

const router = new Router();
export default router;
